﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Threading;
using System.Configuration;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;

namespace SharePoint_Site_Collection_Creator
{

    public delegate void UpdateStatusDelegate(string Message, int Progress);
    public delegate string GetTemplateDelegate(bool result);
    public delegate string GetDatabaseDelegate(bool result);

    public partial class o : Form
    {
        public o()
        {
            InitializeComponent();

            //Intialize the form values
            InitializeValues();


        }

        private bool FindOutIfAdmin()
        {


            //For Currently Logged in users  
            //SPFarm.Local.CurrentUserIsAdministrator();  
 
            bool isFarmAdmin = false;  
 
            SPSecurity.RunWithElevatedPrivileges(delegate()  
            {  
                SPGroup adminGroup = SPAdministrationWebApplication.Local.Sites[0].AllWebs[0].SiteGroups["Farm Administrators"];  
 
                foreach (SPUser user in adminGroup.Users)  
                {
                    if (user.LoginName == Environment.UserDomainName + "\\" + Environment.UserName)  
                    {  
                        isFarmAdmin = true;  
                    }  
                }  
 
            });  
 
            return isFarmAdmin;  
        } 



        /// <summary>
        /// Read the default values from the app.config settings
        /// </summary>
        private void InitializeValues()
        {

            try
            {

                txtSQLServerName.Text = ConfigurationManager.AppSettings.Get("SQLServerName");
                txtWebApplication.Text = ConfigurationManager.AppSettings.Get("WebApplicationURL");
                txtPrimaryOwner.Text = ConfigurationManager.AppSettings.Get("Domain");
                txtSecondaryOwner.Text = ConfigurationManager.AppSettings.Get("Domain");
                txtSiteCollectionURL.Text = ConfigurationManager.AppSettings.Get("SiteCollectionURL");

                populateDatabases();

                using (SPSite siteCollection = new SPSite(ConfigurationManager.AppSettings.Get("SiteCollectionForTemplates")))
                {
                    SPWeb parentWeb = siteCollection.OpenWeb();

                    SPWebTemplateCollection Templates = siteCollection.GetWebTemplates(Convert.ToUInt32(1033));

                    var templates = (from SPWebTemplate sptemplate in Templates
                                     orderby sptemplate.Title
                                     select new { Title = sptemplate.Title, Name = sptemplate.Name }).ToList();

                    cboTemplates.DataSource = templates;
                    cboTemplates.ValueMember = "Name";
                    cboTemplates.DisplayMember = "Title";

                }

                if (FindOutIfAdmin())
                {

                    lblFarmAdmin.Text = Environment.UserDomainName + "\\" + Environment.UserName + " is a Farm Adminstrator";
                    lblFarmAdmin.ForeColor = Color.Green;
                }

                else
                {
                    lblFarmAdmin.Text = Environment.UserDomainName + "\\" + Environment.UserName + " is not a Farm Adminstrator";
                    lblFarmAdmin.ForeColor = Color.Red;
                }

            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

      

        private void UpdateStatus(string Message, int Progress)
        {

            this.progressBar1.Value = Progress;
            this.txtStatus.Text = this.txtStatus.Text + Message + "..." + Environment.NewLine;

        }

        private string GetDatabase(bool Result)
        {
            return cboDatabases.SelectedValue.ToString();
        }

        private string GetTemplate(bool Result)
        {
            return cboTemplates.SelectedValue.ToString();
        }

        /// <summary>
        /// This will create the site collection and content database(if required)
        /// </summary>
        private void CreateSiteCollection()
        {

            //Get the selectedvalue of the templates combobox.  We do it this way to retrieve it from the original thread
            string spTemplate = Invoke(new GetTemplateDelegate(GetTemplate), new object[] { false }).ToString();

            try
            {

                SPSecurity.RunWithElevatedPrivileges(
                delegate
                {
                    // Provide the Web Application URL under which all site collection and sub sites needs to be provisioned 
                    string webApplicationUrl = txtWebApplication.Text;


                    string relativeUrl = txtRelativePath.Text;
                    string siteTitle = txtSiteCollectionName.Text;
                    string siteDescription = "Welcome to your site collection";
                    uint languageCode = 1033;
                    string primaryAdmin = txtPrimaryOwner.Text;
                    string secondaryAdmin = txtSecondaryOwner.Text;

                    //Call the deleate to resolve the cross threading issue
                   Invoke(new UpdateStatusDelegate(UpdateStatus), new object [] { "Initializing Values", 5 });

                   SPWebApplication objWebApplication = SPWebApplication.Lookup(new Uri(webApplicationUrl));

                    Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { "Web Application Opened", 10 });

                    string spDatabase = "";

                    //Create the new content database if the user has checked the New Content database checkbox
                    if (chkNewDatabase.Checked)
                    {
                        Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { "Creating Content Database", 40 });
                        objWebApplication.ContentDatabases.Add(txtSQLServerName.Text, txtContentDatabaseName.Text, null, null, Convert.ToInt32(txtSiteCountWarning.Text), Convert.ToInt32(txtMaximumSiteCount.Text), 1);
                        Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { "Content Database Created", 60 });
                    }
                    else
                    {
                        spDatabase = Invoke(new GetDatabaseDelegate(GetDatabase), new object[] { false }).ToString();
                    }                    

                    //Create host named site collection if chkHostNamed is checked.  Make sure you have a host named web application
                    string url;
                    bool bHostNamed = false;
                    
                    if(chkHostNamed.Checked)
                    {
                        url = txtSiteCollectionURL.Text + txtRelativePath.Text;
                            bHostNamed = true;
                    }
                    else
                    {
                        url = txtRelativePath.Text;
                    }
                     
                    //If the checkbox is checked we'll grab the database name from the New Content Database textbox
                    //otherise we'll get it from the drop down list
                    string databaseName = chkNewDatabase.Checked == true ? txtContentDatabaseName.Text : spDatabase;


                    //Loop through the content databases until we find the matching one
                        foreach (SPContentDatabase contentDB in objWebApplication.ContentDatabases)
                            {
                                if (contentDB.Name == databaseName)
                                {
                                    Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { "Creating Site Collection", 75 });
   
                                    contentDB.Sites.Add(url, siteTitle, siteDescription, languageCode, spTemplate, primaryAdmin, "", "", secondaryAdmin, string.Empty, string.Empty,bHostNamed);
                                    
                                    Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { "Site collection created", 95 }); 
                                }

                            }

                    Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { "Done!", 100 }); 

                });
            }
            catch (Exception ex)
            {

                UpdateStatus("Error Occurred! - " + ex.Message, 100);
            }

        }

        /// <summary>
        /// We'll use the SQL Server System Managent objects to query the SQL Server specified for the list of databases
        /// </summary>
        private void populateDatabases()
        {
            ServerConnection conn = new ServerConnection(ConfigurationManager.AppSettings.Get("SQLServerName"));
            try
            {


                Server srv = new Server(conn);

                //Retrieve the databases that comply with the naming convetion specified in the app.config file
                var databases = (from Database db in srv.Databases
                                 where db.Name.Contains(ConfigurationManager.AppSettings.Get("ContentDatabasePrefix"))
                                 select new { Name = db.Name, ID = db.ID }).ToList();

                //Bind the combobox to the data
                cboDatabases.DataSource = databases;
                cboDatabases.ValueMember = "Name";
                cboDatabases.DisplayMember = "Name";

                conn.Disconnect();
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }

        }

        
        #region "Navigation"

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            NavigateTabs(-1);
        }

        private void linkLabel1_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e)
        {
            NavigateTabs(1);
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            NavigateTabs(1);
        }

        private void lnkBack_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            NavigateTabs(-1);
        }

        private void NavigateTabs(int IndexChange)
        {
            tabControl.SelectedIndex = tabControl.SelectedIndex + IndexChange;
        }

        #endregion

        /// <summary>
        /// Populate the database list when the checkbox is unchecked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkNewDatabase_CheckedChanged(object sender, EventArgs e)
        {
            if (chkNewDatabase.Checked)
            {
                txtContentDatabaseName.ReadOnly = false;
                cboDatabases.DataSource = null;
                cboDatabases.Items.Clear();
            }
            else
            {
                txtContentDatabaseName.ReadOnly = true;
                populateDatabases();
            }
        }

        /// <summary>
        /// Create a new thread and kick off the site collection creation process
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lnkCreate_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e)
        {
            tabControl.SelectedIndex = tabControl.TabPages.Count-1;

            //Start a new thread so the UI stays responsive and reflects the updates to progress bar
            Thread t = new Thread(new ThreadStart(CreateSiteCollection));
            t.Start();      
        }

        #region "Set Current User Fields"

        private void linkCurrentUserPrimary_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            SetCurrentUser(txtPrimaryOwner);
        }

        private void SetCurrentUser(TextBox txtBox)
        {
            txtBox.Text = Environment.UserDomainName + "\\" +  Environment.UserName;
        }

        private void lnkCurrentUserSecondary_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            SetCurrentUser(txtSecondaryOwner);
        }

        #endregion

        private void chkHostNamed_CheckedChanged(object sender, EventArgs e)
        {
            if (chkHostNamed.Checked)
            {
                txtSiteCollectionURL.Enabled = true;
            }
            else
            {
                txtSiteCollectionURL.Enabled = false;
            }
        }


    }

}
